#pragma once
#include "IniRead.h"

class CWndProcThunk
{
#pragma pack(push,1)
	struct _WndProcThunk
	{
		DWORD   m_mov;      // mov dword ptr [esp+0x4], pThis (esp+0x4 is hWnd)
		DWORD   m_this;     //
		BYTE    m_jmp;      // jmp WndProc
		DWORD   m_relproc;   // relative jmp
	}; 
#pragma pack(pop)
public:
	_WndProcThunk thunk;
#pragma warning( push )
#pragma warning(disable:4311)
	void Init(WNDPROC proc, void* pThis)
	{
		thunk.m_mov = 0x042444C7;  //C7 (mov) 44 (dword ptr) 24 ( [esp] ) 04 (+4)  // fourth argument
		thunk.m_this = (DWORD)pThis;
		thunk.m_jmp = 0xe9;
		thunk.m_relproc = (unsigned int)proc - ((unsigned int)this+sizeof(_WndProcThunk));
	}
#pragma warning( pop )
}; 

class CTimer;

class DrawWindow
{
	////////////////////
	//Back Buffer Functions
public:
	int BBWidth;
	int BBHeight;
	HDC BackBufferDC;
	HDC EmptyDC;
public:
	void Put2EmptyDC(HBITMAP hBm_i);

	void ReCreateBackBuffer();
	void ResetBackBuffer();
	
	HDC CreateBufferDC(int width_i, int height_i);
	HDC CreateEmptyDC();

	void DeleteBufferDC();
	void DeleteEmptyDC(HDC& hdc_io);
	void DeleteBufferDC(HDC& hdc_io);

	////////////////////
	//window functions
private:
	int NcX, NcY, NcWidth, NcHeight;
	int XClient, YClient, WidthClient, HeightClient;
	bool Inactive;
	ProfileIni	Ini;
	CWndProcThunk Thunk;
public:
	static HINSTANCE hInstance;
	HWND hWnd;
	bool FullScreen;
	void Initiate();
	void Create();
	void Finish();
protected:
	void OnSize();
	void OnMove();
	void OnkeyDown(BYTE key);
	void OnkeyUp(BYTE key);
	void OnLostFocus(bool Inactive_i);
	void OnMinimized(bool Inactive_i);
	void LoadInitiateFromProfileFile();
	void SaveInitiateToProfileFile();
	LRESULT CALLBACK WndProc(UINT, WPARAM, LPARAM);

	////////////////////
	//drawing functions
private:
	double TPF;//Time Per Frame
	int FrameCount;
	int iFPS;
	LONGLONG LastFrameTicks;
	double TimeElapsed;
	void Draw( );
protected:
	void ChangeScreenMode(bool FullScreen);
public:
	DrawWindow(ResourceManager* fm, CTimer* pT);
	void WaitTilOkToDrawFrame();
	void Present( );
	bool IsProcessingMessage();

	////////////////////
	//hard coding
private:
	static LRESULT CALLBACK WndProcHub(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
	static LRESULT CALLBACK StartWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
	friend class StateMachine;
};

